from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Query
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from sqlalchemy import select
from typing import List, Optional
import os
import uuid
import aiofiles
from pathlib import Path

from app.database import get_db
from app.models.user import User, FileRecord
from app.routers.auth import get_current_active_user
from app.utils.config import settings

router = APIRouter()


def get_file_extension(filename: str) -> str:
    """获取文件扩展名"""
    return Path(filename).suffix.lower()


def generate_unique_filename(original_filename: str) -> str:
    """生成唯一的文件名"""
    file_extension = get_file_extension(original_filename)
    unique_id = str(uuid.uuid4())
    return f"{unique_id}{file_extension}"


def validate_file_type(content_type: str, filename: str) -> bool:
    """验证文件类型"""
    if content_type in settings.ALLOWED_FILE_TYPES:
        return True

    # 根据文件扩展名进行额外验证
    extension = get_file_extension(filename)
    extension_mapping = {
        ".jpg": "image/jpeg",
        ".jpeg": "image/jpeg",
        ".png": "image/png",
        ".gif": "image/gif",
        ".pdf": "application/pdf",
        ".txt": "text/plain",
        ".doc": "application/msword",
        ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    }

    return extension_mapping.get(extension) in settings.ALLOWED_FILE_TYPES


async def save_file_content(content: bytes, filename: str) -> str:
    """直接保存文件内容到磁盘"""
    file_path = os.path.join(settings.UPLOAD_DIR, filename)

    # 确保上传目录存在
    os.makedirs(settings.UPLOAD_DIR, exist_ok=True)

    async with aiofiles.open(file_path, "wb") as f:
        await f.write(content)

    print(f"DEBUG - 文件已保存到: {file_path}")
    print(f"DEBUG - 保存的文件大小: {len(content)} bytes")

    return file_path


@router.post("/upload")
async def upload_file(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
):
    """上传文件"""

    # 先读取文件内容来获取真实大小
    content = await file.read()
    file_size = len(content)

    # 验证文件大小
    if file_size > settings.MAX_FILE_SIZE:
        raise HTTPException(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail=f"文件大小超过限制 ({settings.MAX_FILE_SIZE / 1024 / 1024:.1f}MB)",
        )

    # 验证文件类型
    if not validate_file_type(file.content_type, file.filename):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="不支持的文件类型"
        )

    # 生成唯一文件名
    unique_filename = generate_unique_filename(file.filename)

    try:
        # 保存文件（直接保存已读取的内容）
        file_path = await save_file_content(content, unique_filename)

        # 创建文件记录
        file_record = FileRecord(
            filename=unique_filename,
            original_filename=file.filename,
            file_path=file_path,
            file_size=file_size,
            file_type=file.content_type,
            uploaded_by=current_user.id,
        )

        db.add(file_record)
        db.commit()
        db.refresh(file_record)

        # 构造响应数据
        response_data = {
            "id": file_record.id,
            "filename": file_record.filename,
            "original_filename": file_record.original_filename,
            "file_size": file_record.file_size,
            "file_type": file_record.file_type,
            "upload_url": f"/api/files/download/{file_record.id}",
            "created_at": (
                file_record.created_at.isoformat() if file_record.created_at else None
            ),
        }

        print(f"DEBUG - 文件上传成功，返回数据: {response_data}")
        return response_data

    except Exception as e:
        print(f"ERROR - 文件上传异常: {str(e)}")
        # 如果保存失败，删除已上传的文件
        if "unique_filename" in locals():
            file_path = os.path.join(settings.UPLOAD_DIR, unique_filename)
            if os.path.exists(file_path):
                os.remove(file_path)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"文件上传失败: {str(e)}",
        )


@router.get("/")
def get_files(
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(100, ge=1, le=100, description="返回的记录数"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
):
    """获取文件列表"""
    query = (
        db.query(FileRecord)
        .offset(skip)
        .limit(limit)
        .order_by(FileRecord.created_at.desc())
    )

    # 如果不是超级用户，只显示自己上传的文件
    if not current_user.is_superuser:
        query = query.filter(FileRecord.uploaded_by == current_user.id)

    files = query.all()

    file_list = []
    for file_record in files:
        file_list.append(
            {
                "id": file_record.id,
                "filename": file_record.filename,
                "original_filename": file_record.original_filename,
                "file_size": file_record.file_size,
                "file_type": file_record.file_type,
                "uploaded_by": file_record.uploaded_by,
                "download_url": f"/api/files/download/{file_record.id}",
                "created_at": (
                    file_record.created_at.isoformat()
                    if file_record.created_at
                    else None
                ),
            }
        )

    return file_list


@router.get("/download/{file_id}")
def download_file(
    file_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
):
    """下载文件"""
    file_record = db.query(FileRecord).filter(FileRecord.id == file_id).first()

    if not file_record:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="文件不存在")

    # 检查权限：只有文件上传者或超级用户可以下载
    if file_record.uploaded_by != current_user.id and not current_user.is_superuser:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, detail="没有权限下载该文件"
        )

    # 检查文件是否存在
    if not os.path.exists(file_record.file_path):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="文件已丢失")

    return FileResponse(
        path=file_record.file_path,
        filename=file_record.original_filename,
        media_type=file_record.file_type,
    )


@router.delete("/{file_id}")
def delete_file(
    file_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
):
    """删除文件"""
    file_record = db.query(FileRecord).filter(FileRecord.id == file_id).first()

    if not file_record:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="文件不存在")

    # 检查权限：只有文件上传者或超级用户可以删除
    if file_record.uploaded_by != current_user.id and not current_user.is_superuser:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, detail="没有权限删除该文件"
        )

    # 删除磁盘上的文件
    if os.path.exists(file_record.file_path):
        os.remove(file_record.file_path)

    # 删除数据库记录
    db.delete(file_record)
    db.commit()

    return {"message": "文件删除成功"}
